﻿using System;
using System.Collections.Generic;
using UnityEngine;
using Yoozoo.Core.Common;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace ImageEffects
{
#if UNITY_EDITOR
    [ExecuteInEditMode]
#endif
    public class LightGlobalController :
        QualityListenerMono<LightGlobalController.LightControllerQualitySetting>
    {
        public static Dictionary<string, LightGlobalController> lightControllerMap = new Dictionary<string, LightGlobalController>(10);

        [Serializable]
        public class LightControllerQualitySetting : QualitySetting
        {
            public Light mainLight;
            public Light secondLight;
            public Color shadowColor = new Color(0.1f, 0.1f, 0.1f, 1.0f);
        }
        public bool openQualityListener = false;

        public List<LightElement> AllLightElements = new List<LightElement>();

        public string markLightString;

        protected override void Awake()
        {
            base.Awake();

            foreach (var setting in QualitySettings)
            {
                setting.mainLight.enabled = false;
                setting.secondLight.enabled = false;

                //setting.mainLight.cullingMask = 0;
                //setting.secondLight.cullingMask = 0;
            }

            Add2ControllerMap();
        }

        public void Add2ControllerMap()
        {
            if (lightControllerMap == null)
            {
                lightControllerMap = new Dictionary<string, LightGlobalController>(10);
            }

            if (!string.IsNullOrEmpty(markLightString) && !lightControllerMap.ContainsKey(markLightString))
            {
                lightControllerMap[markLightString] = this;
            }
        }

        protected override void OnEnable()
        {
            if (openQualityListener)
            {
                base.OnEnable();
            }
        }

        protected override void OnDisable()
        {
            if (openQualityListener)
            {
                base.OnDisable();
            }
        }

        public override void ChangeQualitySetting(LightControllerQualitySetting qualitySetting)
        {
            CopyLight(qualitySetting.mainLight, Main_Light);
            CopyLight(qualitySetting.secondLight, Second_Light);
            Shadow_Color = qualitySetting.shadowColor;
            ShaderGlobalSetting(true);
        }

        private void CopyLight(Light original, Light destination)
        {
            destination.color = original.color;
            destination.renderMode = original.renderMode;
            destination.intensity = original.intensity;
            destination.shadows = original.shadows;
            destination.range = original.range;
            destination.type = original.type;
            destination.flare = original.flare;
            destination.bounceIntensity = original.bounceIntensity;
            destination.cullingMask = original.cullingMask;

            destination.transform.position = original.transform.position;
            destination.transform.rotation = original.transform.rotation;
        }


        /// <summary>
        /// 在编辑器模式下 是否只运行一次 表示只生效一次
        /// </summary>
        public bool m_isRunOnceInEditor = true;
        public Light Main_Light = null;
        public Transform Main_Light_Transform;
        public Light Second_Light = null;
        public Transform Second_Light_Transform;
        public Color Shadow_Color = new Color(0.1f, 0.1f, 0.1f, 1.0f);

        public bool frameUpdate = false;

        private Vector4 _mainLightColor;
        private Vector4 _mainLightPos;
        private Vector4 _secondLightColor;
        private Vector4 _secondLightPos;
        private Vector4 _ambienceColor;
        private Vector4 _globalShadowCol;
        private static readonly int MainLightCol = Shader.PropertyToID("_MainLightCol");
        private static readonly int MainLightPos = Shader.PropertyToID("_MainLightPos");
        private static readonly int SecondLightCol = Shader.PropertyToID("_SecondLightCol");
        private static readonly int SecondLightPos = Shader.PropertyToID("_SecondLightPos");
        //private static readonly int AmbienceColor = Shader.PropertyToID("_AmbienceColor");
        private static readonly int GlobalShadowCol = Shader.PropertyToID("_GlobalShadowCol");

        private void Start()
        {
            //for (int i = 0; i < AllLightElements.Count; i++)
            //{
            //    if (AllLightElements[i] == null)
            //    {
            //        AllLightElements.RemoveAt(i);
            //        i--;
            //    }
            //}
            ShaderGlobalSetting(true);

            //if (Main_Light) Main_Light.cullingMask = 0;
            //if (Second_Light) Second_Light.cullingMask = 0;

        }




        private void LateUpdate()
        {
#if UNITY_EDITOR
            if (m_isRunOnceInEditor)
                return;
            ShaderGlobalSetting(false);

#else

            if(frameUpdate){
                ShaderGlobalSetting(false);
            }

#endif
        }

        public void SetMaterial(Material mat)
        {
            mat.SetVector(MainLightCol, _mainLightColor);
            mat.SetVector(MainLightPos, _mainLightPos);
            mat.SetVector(SecondLightCol, _secondLightColor);
            mat.SetVector(SecondLightPos, _secondLightPos);
        }

        public void ShaderGlobalSetting(bool force)
        {
            if (Main_Light == null || Main_Light_Transform == null || Second_Light == null || Second_Light_Transform == null)
            {
                return;
            }

            Vector4 mainLightColor = Main_Light.color * Main_Light.intensity;
            Vector4 mainLightPos = Main_Light_Transform.forward;
            Vector4 secondLightColor = Second_Light.color * Second_Light.intensity;
            Vector4 secondLightPos = Second_Light_Transform.forward;
            Vector4 ambienceColor = RenderSettings.ambientLight;
            Vector4 globalShadowCol = Shadow_Color;

            if (mainLightColor == _mainLightColor &&
                mainLightPos == _mainLightPos &&
                secondLightColor == _secondLightColor &&
                secondLightPos == _secondLightPos &&
                ambienceColor == _ambienceColor &&
                globalShadowCol == _globalShadowCol)
            {

                if (!force)
                {
                    return;
                }
            }

            _mainLightColor = mainLightColor;
            _mainLightPos = mainLightPos;
            _secondLightColor = secondLightColor;
            _secondLightPos = secondLightPos;
            _ambienceColor = ambienceColor;
            _globalShadowCol = globalShadowCol;


            Shader.EnableKeyword("_GLOBALLIGHTCONTROLLER");
            Shader.SetGlobalVector(MainLightCol, _mainLightColor);
            Shader.SetGlobalVector(MainLightPos, _mainLightPos);
            Shader.SetGlobalVector(SecondLightCol, _secondLightColor);
            Shader.SetGlobalVector(SecondLightPos, _secondLightPos);
            //Shader.SetGlobalVector(AmbienceColor, _ambienceColor);
            Shader.SetGlobalVector(GlobalShadowCol, _globalShadowCol);

        }

        // private Dictionary<LightElement, Dictionary<Material, MaterialPropertyBlock>> blockPool =
        //     new Dictionary<LightElement, Dictionary<Material, MaterialPropertyBlock>>();
        public void SingleShaderSetting(LightElement lightElement)
        {
            //#if UNITY_EDITOR
            //            if (lightElement != null)
            //            {
            //                if (lightElement.LightMaterials != null)
            //                {
            //                    lightElement.LightMaterials.Clear();
            //                }
            //                else
            //                {
            //                    lightElement.LightMaterials = new List<Material>(10);
            //                }
            //            }
            //#endif
            //            // if (!blockPool.TryGetValue(lightElement, out var pool))
            //            // {
            //            //     pool = new Dictionary<Material, MaterialPropertyBlock>();
            //            //     blockPool.Add(lightElement,pool);
            //            // }

            //            foreach (var lightRenderer in lightElement.LightRenderers)
            //            {
            //                if (lightRenderer == null)
            //                {
            //                    continue;
            //                }
            //#if UNITY_EDITOR
            //                foreach (var sharedMaterial in lightRenderer.sharedMaterials)
            //                {
            //                    if (sharedMaterial != null /*&& sharedMaterial.HasProperty("_MainLightCol")*/)
            //                    {
            //                        Material mat = sharedMaterial;
            //                        if (mat)
            //                        {
            //                            lightElement.LightMaterials.Add(mat);
            //                        }
            //                    }
            //                }
            //#endif        
            //                lightRenderer.SetPropertyBlock(cachedPropertyBlock);
            //            }
        }

        private MaterialPropertyBlock cachedPropertyBlock { get; set; }

        public void AddLightElement(LightElement lightElement)
        {
            //if (lightElement == null)
            //{
            //    return;
            //}

            //if (AllLightElements.Contains(lightElement))
            //{
            //    return;
            //}
            //AllLightElements.Add(lightElement);
            ////SingleShaderSetting(lightElement);

            //lightElement.OnSetController(this);

        }

        public void RemoveLightingElement(LightElement lightElement)
        {
            //if (lightElement == null)
            //{
            //    return;
            //}

            //if (AllLightElements.Contains(lightElement))
            //{
            //    AllLightElements.Remove(lightElement);
            //}

            // if (blockPool.ContainsKey(lightElement))
            // {
            //     blockPool.Remove(lightElement);
            // }
        }
        public void ShaderSetting(bool force)
        {
            //    if (Main_Light == null || Main_Light_Transform == null || Second_Light == null || Second_Light_Transform == null)
            //    {
            //        return;
            //    }

            //    Vector4 mainLightColor = Main_Light.color * Main_Light.intensity;
            //    Vector4 mainLightPos = Main_Light_Transform.forward;
            //    Vector4 secondLightColor = Second_Light.color * Second_Light.intensity;
            //    Vector4 secondLightPos = Second_Light_Transform.forward;
            //    Vector4 ambienceColor = RenderSettings.ambientLight;
            //    Vector4 globalShadowCol = Shadow_Color;

            //    if (mainLightColor == _mainLightColor &&
            //        mainLightPos == _mainLightPos &&
            //        secondLightColor == _secondLightColor &&
            //        secondLightPos == _secondLightPos &&
            //        ambienceColor == _ambienceColor &&
            //        globalShadowCol == _globalShadowCol)
            //    {

            //        if (!force)
            //        {
            //            return;
            //        }
            //    }

            //    _mainLightColor = mainLightColor;
            //    _mainLightPos = mainLightPos;
            //    _secondLightColor = secondLightColor;
            //    _secondLightPos = secondLightPos;
            //    _ambienceColor = ambienceColor;
            //    _globalShadowCol = globalShadowCol;

            //    if (cachedPropertyBlock == null)
            //    {
            //        cachedPropertyBlock = new MaterialPropertyBlock();
            //    }


            //    cachedPropertyBlock.SetVector(MainLightCol, _mainLightColor);
            //    cachedPropertyBlock.SetVector(MainLightPos, _mainLightPos);
            //    cachedPropertyBlock.SetVector(SecondLightCol, _secondLightColor);
            //    cachedPropertyBlock.SetVector(SecondLightPos, _secondLightPos);
            //    cachedPropertyBlock.SetVector(AmbienceColor, _ambienceColor);
            //    cachedPropertyBlock.SetVector(GlobalShadowCol, _globalShadowCol);

            //    if (AllLightElements != null)
            //    {
            //        foreach (var lightElement in AllLightElements)
            //        {
            //            if (lightElement != null)
            //            {
            //                SingleShaderSetting(lightElement);
            //            }
            //        }
            //    }
        }

        //        


        private void OnDestroy()
        {
            //if (AllLightElements != null)
            //{
            //    foreach (var lightElement in AllLightElements)
            //    {
            //        if (lightElement)
            //        {
            //            lightElement.OnRemoved();
            //        }
            //    }
            //    AllLightElements = null;
            //}

            //if (!string.IsNullOrEmpty(markString))
            //{
            //    lightControllerMap.Remove(markString);
            //}

        }


#if UNITY_EDITOR

        private void OnValidate()
        {
            ShaderGlobalSetting(true);
        }

#endif
    }
}
